
package com.hlkj.pay.gateway.merchant.impl;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantAccessExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.access.*;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouAppChannelParams;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.merchant.*;
import com.hlkj.pay.dto.merchant.access.MerchantAccessResDto;
import com.hlkj.pay.dto.pay.PayCommonAppDto;
import com.hlkj.pay.dto.pay.PayWayQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.gateway.merchant.IMerchantAccessGateway;
import com.hlkj.pay.infrastructure.model.common.CommonAppDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.common.ICommonAppConfigService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IPayWayService;
import com.hlkj.pay.service.pay.IProviderService;
import com.hlkj.pay.vo.order.req.MerchantChannelSplitReq;
import com.hlkj.pay.vo.order.req.MerchantProductReq;
import com.hlkj.pay.vo.order.req.MerchantTermAddReq;
import com.hlkj.pay.vo.order.resp.MerchantProductQueryResp;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import jodd.util.StringPool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zhou.long
 * @date 2024/11/28 6:58
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantAccessGatewayImpl implements IMerchantAccessGateway {

    private final IMerchantConfigService merchantConfigService;

    private final IPayChannelService payChannelService;

    private final IPayWayService payWayService;

    private final IProviderService providerService;

    private final ICommonAppConfigService commonAppConfigService;

    private final ExtensionExecutor extensionExecutor;

    private final IMerchantApplicationService merchantApplicationService;

    @Value("${hlkj.pay.test:false}")
    private boolean test;

    @Value("${hlkj.domain}")
    private String domain;

    @Override
    public CommonResult<Void> channelConfigCheck(ProviderChannelConfigDO providerChannelConfig) {
        ChannelMerchantAccessCommonContext merchantAccessCommonContext = new ChannelMerchantAccessCommonContext();
        merchantAccessCommonContext.setProviderChannelConfig(providerChannelConfig);
        merchantAccessCommonContext.setTest(test);
        if(extensionExist(providerChannelConfig.getChannelCode())){
            extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(providerChannelConfig.getChannelCode()),
                    ex -> ex.channelConfigCheck(merchantAccessCommonContext));
            if (!merchantAccessCommonContext.isProcessStatus()) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), merchantAccessCommonContext.getRemark());
            }
        }
        return CommonResult.success();
    }

    @Override
    public boolean extensionExist(String channelCode) {
        return extensionExecutor.executeExist(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(channelCode));
    }

    @Override
    public CommonResult<MerchantAccessResDto> merchantAccess(MerchantAccessDto merchantAccessDto) {
        // Long id = merchantAccessDto.getMerchantAccessInfo().getId();
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        // MerchantAccessBusinessDO merchantAccessBusinessDO =
        // merchantAccessDto.getMerchantAccessBusiness();
        // String requestUrl =
        // extensionExecutor.execute(ChannelMerchantAccessExtPt.class,
        // BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
        // ex -> ex.requestUrl(merchantAccessDto));
        String requestUrl = "merchantAccess";
        // merchantAccessDto.setPayChannelRequest(payChannelService.queryRequestByAccessId(merchantAccessInfoDO.getRequestId(),
        // requestUrl));
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });
        merchantFeeConfigList = merchantFeeConfigList.stream().filter(merchantFeeConfig -> merchantFeeConfig.getPayWayDO() != null).collect(Collectors.toList());
        Set<Long> appIds = new HashSet<>();
        if (providerChannelConfigDO != null) {
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatPubIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatPubIdList());
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatMiniIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatMiniIdList());
            appIds.add(providerChannelConfigDO.getAlipayPubId());
            appIds.add(providerChannelConfigDO.getAlipayMiniId());
        }
        appIds.remove(null);
        ChannelMerchantAccessContext channelMerchantAccessContext = new ChannelMerchantAccessContext();
        channelMerchantAccessContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantAccessContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessContext.setMerchantFeeConfigList(merchantFeeConfigList);
        channelMerchantAccessContext.setBeforePayChannelRequestDO(payChannelService.queryRequestByAccessId(merchantAccessInfoDO.getRequestId(), requestUrl));
        channelMerchantAccessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_ACCESS_STATUS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH
                + merchantAccessInfoDO.getProviderCode());
        channelMerchantAccessContext.setPayCommonAppList(payCommonAppList(appIds, merchantAccessDto));
        channelMerchantAccessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.merchantAccess(channelMerchantAccessContext));
        PayChannelRequestDO payChannelRequestDO = channelMerchantAccessContext.getPayChannelRequestDO();
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(merchantAccessInfoDO.getSn());
            payChannelRequestDO.setRequestUrl(requestUrl);
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
            if(StrUtil.isNotEmpty(payChannelRequestDO.getApplyNo())){
                merchantAccessResDto.setApplyNo(payChannelRequestDO.getApplyNo());
            }
        }
        if (channelMerchantAccessContext.isProcessStatus()) {
            merchantAccessResDto.setRequestId(merchantAccessInfoDO.getRequestId());
            merchantAccessResDto.setAccessStatus(channelMerchantAccessContext.getAccessStatus());
            merchantAccessResDto.setSubMchId(merchantAccessInfoDO.getSubMchId());
            if(StrUtil.isNotEmpty(merchantAccessInfoDO.getApplyNo())){
                merchantAccessResDto.setApplyNo(merchantAccessInfoDO.getApplyNo());
            }
            if(StrUtil.isNotEmpty(merchantAccessInfoDO.getExtendA())){
                merchantAccessResDto.setExtendA(merchantAccessInfoDO.getExtendA());
            }
            if(StrUtil.isNotEmpty(merchantAccessInfoDO.getRemark())){
                merchantAccessResDto.setRemark(merchantAccessInfoDO.getRemark());
            }
            if (channelMerchantAccessContext.getAuditStatus() != null) {
                merchantAccessResDto.setAuditStatus(channelMerchantAccessContext.getAuditStatus());
            }
            merchantAccessResDto.setSignLinks(channelMerchantAccessContext.getSignLinks());
            return CommonResult.success(merchantAccessResDto);
        }
        else {
            if (StringUtils.hasText(channelMerchantAccessContext.getMerchantAccessDto().getMerchantAccessInfo().getSubMchId()))
                merchantAccessDto.getMerchantAccessInfo().setSubMchId(channelMerchantAccessContext.getMerchantAccessDto().getMerchantAccessInfo().getSubMchId());

            if (StringUtils.hasText(channelMerchantAccessContext.getMerchantAccessDto().getMerchantAccessInfo().getApplyNo()))
                merchantAccessDto.getMerchantAccessInfo().setApplyNo(channelMerchantAccessContext.getMerchantAccessDto().getMerchantAccessInfo().getApplyNo());

            return CommonResult.error(0, channelMerchantAccessContext.getRemark());
        }
    }

    @Override
    public CommonResult<MerchantAccessResDto> processSign(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });

        ChannelMerchantAccessSignContext channelMerchantAccessSignContext = new ChannelMerchantAccessSignContext();
        channelMerchantAccessSignContext.setMerchantAccessInfoDO(merchantAccessInfoDO);
        channelMerchantAccessSignContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessSignContext.setMerchantFeeConfigList(merchantFeeConfigList);
        channelMerchantAccessSignContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.merchantSign(channelMerchantAccessSignContext));
        if (channelMerchantAccessSignContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            merchantAccessResDto.setAccessStatus(channelMerchantAccessSignContext.getAccessStatus());
            if (channelMerchantAccessSignContext.getAuditStatus() != null)
                merchantAccessResDto.setAuditStatus(channelMerchantAccessSignContext.getAuditStatus());
            merchantAccessResDto.setSignLinks(channelMerchantAccessSignContext.getSignLinks());
            return CommonResult.success(merchantAccessResDto);
        } else {
            return CommonResult.error(0, channelMerchantAccessSignContext.getRemark());
        }
    }

    @Override
    public CommonResult<MerchantAccessResDto> processSignQuery(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantAccessSignContext channelMerchantAccessSignContext = new ChannelMerchantAccessSignContext();
        channelMerchantAccessSignContext.setMerchantAccessInfoDO(merchantAccessInfoDO);
        channelMerchantAccessSignContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessSignContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.merchantSignQuery(channelMerchantAccessSignContext));
        if (channelMerchantAccessSignContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            merchantAccessResDto.setAuditStatus(channelMerchantAccessSignContext.getAuditStatus());
            merchantAccessResDto.setAccessStatus(channelMerchantAccessSignContext.getAccessStatus());
            merchantAccessResDto.setSignLinks(channelMerchantAccessSignContext.getSignLinks());
            if (StringUtils.hasText(merchantAccessInfoDO.getSubMchId())) {
                merchantAccessResDto.setSubMchId(merchantAccessInfoDO.getSubMchId());
            }
            if(StrUtil.isNotEmpty(merchantAccessInfoDO.getExtendA())){
                merchantAccessResDto.setExtendA(merchantAccessInfoDO.getExtendA());
            }
            return CommonResult.success(merchantAccessResDto);
        }
        else {
            return CommonResult.error(0, channelMerchantAccessSignContext.getRemark());
        }
    }

    @Override
    public CommonResult<MerchantAccessResDto> merchantBusinessOpen(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        Set<Long> appIds = new HashSet<>();
        if (providerChannelConfigDO != null) {
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatPubIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatPubIdList());
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatMiniIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatMiniIdList());
            appIds.add(providerChannelConfigDO.getAlipayPubId());
            appIds.add(providerChannelConfigDO.getAlipayMiniId());
        }

        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });
        ChannelMerchantBusinessContext channelMerchantBusinessContext = new ChannelMerchantBusinessContext();
        channelMerchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantBusinessContext.setMerchantFeeConfigList(merchantFeeConfigList);
        channelMerchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_STATUS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setAsyncErrorReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_SUCCESS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setAsyncTransUrl(
                domain + MerchantExtConstant.MERCHANT_TRANS_ASYNC_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setPayCommonAppList(payCommonAppList(appIds, merchantAccessDto));
        channelMerchantBusinessContext.setDomain(domain);
        channelMerchantBusinessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.merchantBusinessOpen(channelMerchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = channelMerchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        if (channelMerchantBusinessContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            merchantAccessResDto.setAccessStatus(channelMerchantBusinessContext.getAccessStatus());
            merchantAccessResDto.setAuditStatus(channelMerchantBusinessContext.getAuditStatus());
            merchantAccessResDto.setMerchantAccessAuths(channelMerchantBusinessContext.getMerchantAccessAuthList());
            if (StringUtils.hasText(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getSubMchId()))
                merchantAccessResDto.setSubMchId(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getSubMchId());
            merchantAccessResDto.setExtendA(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getExtendA());
            merchantAccessResDto.setExtendB(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getExtendB());
            merchantAccessResDto.setSignLinks(channelMerchantBusinessContext.getSignLinks());
            merchantAccessResDto.setRemark(channelMerchantBusinessContext.getRemark());
            merchantAccessResDto.setLastAccessStatus(channelMerchantBusinessContext.getLastAccessStatus());
            return CommonResult.success(merchantAccessResDto);
        }
        else {
            CommonResult<MerchantAccessResDto> error = CommonResult.error(0, channelMerchantBusinessContext.getRemark());
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            merchantAccessResDto.setLastAccessStatus(channelMerchantBusinessContext.getLastAccessStatus());
            error.setData(merchantAccessResDto);
            return error;
        }
    }

    @Override
    public CommonResult<MerchantAccessResDto> wechatConfigInit(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        Set<Long> appIds = new HashSet<>();
        if (providerChannelConfigDO != null) {
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatPubIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatPubIdList());
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatMiniIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatMiniIdList());
            appIds.add(providerChannelConfigDO.getAlipayPubId());
            appIds.add(providerChannelConfigDO.getAlipayMiniId());
        }
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });

        ChannelMerchantBusinessContext channelMerchantBusinessContext = new ChannelMerchantBusinessContext();
        channelMerchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantBusinessContext.setMerchantFeeConfigList(merchantFeeConfigList);
        channelMerchantBusinessContext.setPayCommonAppList(payCommonAppList(appIds, merchantAccessDto));
        channelMerchantBusinessContext.setDomain(domain);
        channelMerchantBusinessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.wechatConfigInit(channelMerchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = channelMerchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        merchantAccessResDto.setAccessStatus(channelMerchantBusinessContext.getAccessStatus());
        merchantAccessResDto.setAuditStatus(channelMerchantBusinessContext.getAuditStatus());
        merchantAccessResDto.setMerchantAccessAuths(channelMerchantBusinessContext.getMerchantAccessAuthList());
        return CommonResult.success(merchantAccessResDto);
    }

    @Override
    public CommonResult<Void> wechatConfigAdd(MerchantAccessDto merchantAccessDto, MerchantAccessAuthDO merchantAccessAuthDO, MerchantWechatConfigDto merchantWechatConfigDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantBusinessContext channelMerchantBusinessContext = new ChannelMerchantBusinessContext();
        channelMerchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_STATUS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setAsyncErrorReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_SUCCESS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setAsyncTransUrl(
                domain + MerchantExtConstant.MERCHANT_TRANS_ASYNC_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        channelMerchantBusinessContext.setMerchantWechatConfigDto(merchantWechatConfigDto);
        channelMerchantBusinessContext.setMerchantAccessAuth(merchantAccessAuthDO);
        channelMerchantBusinessContext.setDomain(domain);
        channelMerchantBusinessContext.setTest(test);

        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.wechatConfigAdd(channelMerchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = channelMerchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getId().toString());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        if (channelMerchantBusinessContext.isProcessStatus()) {
            return CommonResult.success();
        }
        return CommonResult.error(1, channelMerchantBusinessContext.getRemark());
    }

    @Override
    public CommonResult<MerchantAccessResDto> wechatConfigQuery(MerchantAccessDto merchantAccessDto, List<MerchantAccessAuthDO> wechatAccessAuthDbList) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext = new ChannelMerchantAccessAuthQueryContext();
        channelMerchantAccessAuthQueryContext.setMerchantAccessAuthList(wechatAccessAuthDbList);
        channelMerchantAccessAuthQueryContext.setMerchantAccessInfo(merchantAccessDto.getMerchantAccessInfo());
        channelMerchantAccessAuthQueryContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessAuthQueryContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.wechatConfigQuery(channelMerchantAccessAuthQueryContext));
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        merchantAccessResDto.setAuditStatus(channelMerchantAccessAuthQueryContext.getAuditStatus());
        merchantAccessResDto.setMerchantWechatConfigListDto(channelMerchantAccessAuthQueryContext.getMerchantWechatConfigListDto());
        return CommonResult.success(merchantAccessResDto);
    }

    @Override
    public CommonResult<MerchantAccessResDto> wechatAuthConfig(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantBusinessContext merchantBusinessContext = new ChannelMerchantBusinessContext();
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });
        Set<Long> appIds = new HashSet<>();
        if (providerChannelConfigDO != null) {
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatPubIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatPubIdList());
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatMiniIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatMiniIdList());
            appIds.add(providerChannelConfigDO.getAlipayPubId());
            appIds.add(providerChannelConfigDO.getAlipayMiniId());
        }
        merchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        merchantBusinessContext.setMerchantFeeConfigList(merchantFeeConfigList);
        merchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_STATUS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH
                + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setAsyncErrorReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_SUCCESS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setAsyncTransUrl(
                domain + MerchantExtConstant.MERCHANT_TRANS_ASYNC_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setPayCommonAppList(payCommonAppList(appIds, merchantAccessDto));
        merchantBusinessContext.setDomain(domain);
        merchantBusinessContext.setTest(test);
        merchantBusinessContext.setMerchantAccessAuthList(merchantAccessDto.getMerchantAccessAuthList());
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.wechatAuthConfig(merchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = merchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        if (merchantBusinessContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            if (merchantBusinessContext.getAccessStatus() != null) {
                merchantAccessResDto.setAccessStatus(merchantBusinessContext.getAccessStatus());
            }
            if(StrUtil.isNotEmpty(merchantBusinessContext.getExtendA())){
                merchantAccessResDto.setExtendA(merchantBusinessContext.getExtendA());
            }
            if (merchantBusinessContext.getAuditStatus() != null) {
                merchantAccessResDto.setAuditStatus(merchantBusinessContext.getAuditStatus());
            }
            if (merchantBusinessContext.getMerchantAccessAuthList() != null) {
                merchantAccessResDto.setMerchantAccessAuths(merchantBusinessContext.getMerchantAccessAuthList());
            }
            return CommonResult.success(merchantAccessResDto);
        }
        return CommonResult.error(1, merchantBusinessContext.getRemark());
    }

    @Override
    public CommonResult<MerchantAccessResDto> wechatAuthConfigQuery(MerchantAccessDto merchantAccessDto, List<MerchantAccessAuthDO> wechatAccessAuthDbList) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext = new ChannelMerchantAccessAuthQueryContext();
        channelMerchantAccessAuthQueryContext.setMerchantAccessInfo(merchantAccessDto.getMerchantAccessInfo());
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        channelMerchantAccessAuthQueryContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessAuthQueryContext.setMerchantAccessAuthDbList(wechatAccessAuthDbList);
        channelMerchantAccessAuthQueryContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.wechatAuthQuery(channelMerchantAccessAuthQueryContext));
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        merchantAccessResDto.setAuditStatus(channelMerchantAccessAuthQueryContext.getAuditStatus());
        merchantAccessResDto.setMerchantAccessAuths(channelMerchantAccessAuthQueryContext.getMerchantAccessAuthList());
        return CommonResult.success(merchantAccessResDto);

    }

    @Override
    public boolean authConfigQueryType(String channelCode) {
        try {
            return extensionExecutor.execute(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(channelCode), ex -> ex.authConfigQueryType());
        }
        catch (Exception e) {
            return false;
        }
    }

    @Override
    public CommonResult<MerchantAccessResDto> aliAuthConfig(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantBusinessContext merchantBusinessContext = new ChannelMerchantBusinessContext();
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantAccessInfoDO.getSn());
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        merchantFeeConfigList.stream().forEach(merchantConfig -> {
            merchantConfig.setPayWayDO(payWayService.queryByCode(merchantConfig.getPayWayCode()));
        });
        Set<Long> appIds = new HashSet<>();
        if (providerChannelConfigDO != null) {
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatPubIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatPubIdList());
            if (!CollectionUtils.isEmpty(providerChannelConfigDO.getWechatMiniIdList()))
                appIds.addAll(providerChannelConfigDO.getWechatMiniIdList());
            appIds.add(providerChannelConfigDO.getAlipayPubId());
            appIds.add(providerChannelConfigDO.getAlipayMiniId());
        }
        merchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        merchantBusinessContext.setMerchantFeeConfigList(merchantFeeConfigList);
        merchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_STATUS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH
                + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setAsyncErrorReturnUrl(domain + MerchantExtConstant.MERCHANT_BUSINESS_SUCCESS_CALLBACK_URL + merchantAccessInfoDO.getChannelCode()
                + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setAsyncTransUrl(
                domain + MerchantExtConstant.MERCHANT_TRANS_ASYNC_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH + merchantAccessInfoDO.getProviderCode());
        merchantBusinessContext.setPayCommonAppList(payCommonAppList(appIds, merchantAccessDto));
        merchantBusinessContext.setDomain(domain);
        merchantBusinessContext.setTest(test);
        merchantBusinessContext.setMerchantAccessAuthList(merchantAccessDto.getMerchantAccessAuthList());
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.alipayAuthConfig(merchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = merchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        if (merchantBusinessContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            if (merchantBusinessContext.getAccessStatus() != null) {
                merchantAccessResDto.setAccessStatus(merchantBusinessContext.getAccessStatus());
            }
            if(StrUtil.isNotEmpty(merchantBusinessContext.getExtendB())){
                merchantAccessResDto.setExtendB(merchantBusinessContext.getExtendB());
            }
            if (merchantBusinessContext.getAuditStatus() != null) {
                merchantAccessResDto.setAuditStatus(merchantBusinessContext.getAuditStatus());
            }
            if (merchantBusinessContext.getMerchantAccessAuthList() != null) {
                merchantAccessResDto.setMerchantAccessAuths(merchantBusinessContext.getMerchantAccessAuthList());
            }
            return CommonResult.success(merchantAccessResDto);
        }
        return CommonResult.error(1, merchantBusinessContext.getRemark());
    }

    @Override
    public CommonResult<MerchantAccessResDto> aliAuthConfigQuery(MerchantAccessDto merchantAccessDto, List<MerchantAccessAuthDO> aliAccessAuthDbList) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext = new ChannelMerchantAccessAuthQueryContext();
        channelMerchantAccessAuthQueryContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantAccessAuthQueryContext.setMerchantAccessInfo(merchantAccessDto.getMerchantAccessInfo());
        channelMerchantAccessAuthQueryContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessAuthQueryContext.setMerchantAccessAuthDbList(aliAccessAuthDbList);
        channelMerchantAccessAuthQueryContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.alipayAuthQuery(channelMerchantAccessAuthQueryContext));
        MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
        merchantAccessResDto.setAuditStatus(channelMerchantAccessAuthQueryContext.getAuditStatus());
        merchantAccessResDto.setMerchantAccessAuths(channelMerchantAccessAuthQueryContext.getMerchantAccessAuthList());
        return CommonResult.success(merchantAccessResDto);
    }

    @Override
    public CommonResult<MerchantAccessResDto> merchantAccessQuery(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext = new ChannelMerchantAccessQueryContext();
        channelMerchantAccessQueryContext.setMerchantAccessInfo(merchantAccessInfoDO);
        channelMerchantAccessQueryContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessQueryContext.setTest(test);
        channelMerchantAccessQueryContext.setMerchantAccessAuthDbList(merchantAccessDto.getMerchantAccessAuthList());
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.merchantAccessQuery(channelMerchantAccessQueryContext));
        if (channelMerchantAccessQueryContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            if (channelMerchantAccessQueryContext.getAccessStatus() != null) {
                merchantAccessResDto.setAccessStatus(channelMerchantAccessQueryContext.getAccessStatus());
            }
            if (channelMerchantAccessQueryContext.getAuditStatus() != null) {
                merchantAccessResDto.setAuditStatus(channelMerchantAccessQueryContext.getAuditStatus());
            }

            if (StringUtils.hasText(channelMerchantAccessQueryContext.getRemark())) {
                merchantAccessResDto.setRemark(channelMerchantAccessQueryContext.getRemark());
            }
            MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessQueryContext.getMerchantAccessInfo();
            merchantAccessResDto.setExtendA(merchantAccessInfo.getExtendA());
            merchantAccessResDto.setExtendB(merchantAccessInfo.getExtendB());
            merchantAccessResDto.setSubMchId(merchantAccessInfo.getSubMchId());
            merchantAccessResDto.setMerchantAccessAuths(channelMerchantAccessQueryContext.getMerchantAccessAuthList());
            merchantAccessResDto.setSignLinks(channelMerchantAccessQueryContext.getSignLinks());
            merchantAccessResDto.setSubMchId(merchantAccessInfo.getSubMchId());
            // merchantAccessResDto.setExtendB(merchantAccessInfo.getExtendB());
            return CommonResult.success(merchantAccessResDto);
        }
        return CommonResult.error(1, channelMerchantAccessQueryContext.getRemark());
    }

    @Override
    public CommonResult<String> termAdd(MerchantAccessDto merchantAccessDto, MerchantAppChannelDO merchantAppChannelDO, MerchantTermAddReq merchantTermAddReq) {
        FuYouAppChannelParams fuYouAppChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), FuYouAppChannelParams.class);
        if (StringUtils.hasText(fuYouAppChannelParams.getTermId())) {
            return CommonResult.success(fuYouAppChannelParams.getTermId());
        }
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode());
        ChannelMerchantTermContext channelMerchantTermContext = new ChannelMerchantTermContext();
        channelMerchantTermContext.setMerchantTermAddReq(merchantTermAddReq);
        channelMerchantTermContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantTermContext.setTest(test);
        channelMerchantTermContext.setMerchantAppChannelDO(merchantAppChannelDO);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()), ex -> ex.termAdd(channelMerchantTermContext));
        if (channelMerchantTermContext.isProcessStatus()) {
            channelMerchantTermContext.getTermId();
            AccessChannelParamsDto accessChannelParamsDto = new AccessChannelParamsDto();
            accessChannelParamsDto.setTeamId(channelMerchantTermContext.getTermId());
            accessChannelParamsDto.setSubMchId(merchantAppChannelDO.getSubMchId());
            String channelParams = extensionExecutor.execute(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                    ex -> ex.channelParams(accessChannelParamsDto));
            merchantApplicationService.updateAppConfig(merchantAppChannelDO, channelParams);
            MerchantWechatConfigDto merchantWechatConfigDto = new MerchantWechatConfigDto();
            merchantWechatConfigDto.setAppId("wx42c9727eaa151e8b");
            // 富友可以不传merchantAccessAuthDO
            wechatConfigAdd(merchantAccessDto, null, merchantWechatConfigDto);
        }
        return CommonResult.error(1, channelMerchantTermContext.getRemark());
    }

    @Override
    public CommonResult<MerchantAccessResDto> reloadMerchantAuth(MerchantAccessDto merchantAccessDto) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantBusinessContext channelMerchantBusinessContext = new ChannelMerchantBusinessContext();
        channelMerchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantBusinessContext.setDomain(domain);
        channelMerchantBusinessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.reloadMerchantAuth(channelMerchantBusinessContext));
        if (channelMerchantBusinessContext.isProcessStatus()) {
            MerchantAccessResDto merchantAccessResDto = new MerchantAccessResDto();
            merchantAccessResDto.setAccessStatus(channelMerchantBusinessContext.getAccessStatus());
            merchantAccessResDto.setAuditStatus(channelMerchantBusinessContext.getAuditStatus());
            merchantAccessResDto.setMerchantAccessAuths(channelMerchantBusinessContext.getMerchantAccessAuthList());
            merchantAccessResDto.setExtendA(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getExtendA());
            merchantAccessResDto.setExtendB(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo().getExtendB());
            return CommonResult.success(merchantAccessResDto);
        }
        else {
            return CommonResult.error(0, channelMerchantBusinessContext.getRemark());
        }
    }

    @Override
    public CommonResult<MerchantAccessAuthDO> easySplit(MerchantAccessDto merchantAccessDto, MerchantAppChannelDO merchantAppChannelDO,
            MerchantChannelSplitReq merchantChannelSplitReq) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantBusinessContext merchantBusinessContext = new ChannelMerchantBusinessContext();
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        merchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        merchantBusinessContext.setMerchantChannelSplitReq(merchantChannelSplitReq);
        merchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_CHANNEL_SPLIT_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH
                + merchantAccessInfoDO.getProviderCode() + StringPool.SLASH + merchantAccessInfoDO.getRequestId());
        merchantBusinessContext.setDomain(domain);
        merchantBusinessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()), ex -> ex.channelSplit(merchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = merchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        CommonResult<MerchantAccessAuthDO> commonResult;
        if (merchantBusinessContext.isProcessStatus()) {
            commonResult = CommonResult.success();
        }
        else {
            commonResult = CommonResult.error(1, merchantBusinessContext.getRemark());
        }
        commonResult.setData(merchantBusinessContext.getMerchantAccessAuthDO());
        return commonResult;
    }

    @Override
    public CommonResult<Void> productUpdate(MerchantAccessDto merchantAccessDto, MerchantAppChannelDO merchantAppChannelDO, MerchantProductReq merchantProductReq) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantBusinessContext merchantBusinessContext = new ChannelMerchantBusinessContext();
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        merchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        merchantBusinessContext.setMerchantProductReq(merchantProductReq);
        merchantBusinessContext.setAsyncReturnUrl(domain + MerchantExtConstant.MERCHANT_PRODUCT_UPDATE_CALLBACK_URL + merchantAccessInfoDO.getChannelCode() + StringPool.SLASH
                + merchantAccessInfoDO.getProviderCode() + StringPool.SLASH + merchantAccessInfoDO.getRequestId());
        merchantBusinessContext.setDomain(domain);
        merchantBusinessContext.setTest(test);
        extensionExecutor.executeVoid(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()), ex -> ex.productUpdate(merchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = merchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        CommonResult<Void> commonResult = null;
        if (merchantBusinessContext.isProcessStatus()) {
            commonResult = CommonResult.success();
        }
        else {
            commonResult = CommonResult.error(1, merchantBusinessContext.getRemark());
        }
        return commonResult;
    }

    @Override
    public CommonResult<MerchantProductQueryResp> productQuery(MerchantAccessDto merchantAccessDto, MerchantAppChannelDO merchantAppChannelDO, MerchantProductReq merchantProductQueryReq) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ChannelMerchantBusinessContext merchantBusinessContext = new ChannelMerchantBusinessContext();
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        merchantBusinessContext.setProviderChannelConfig(providerChannelConfigDO);
        merchantBusinessContext.setMerchantAccessDto(merchantAccessDto);
        merchantBusinessContext.setDomain(domain);
        merchantBusinessContext.setTest(test);
        MerchantProductQueryResp resp = extensionExecutor.execute(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()), ex -> ex.productQuery(merchantBusinessContext));
        PayChannelRequestDO payChannelRequestDO = merchantBusinessContext.getPayChannelRequestDO();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(merchantAccessInfoDO.getRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(merchantAccessInfoDO.getChannelCode());
            payChannelRequestDO.setProviderCode(merchantAccessInfoDO.getProviderCode());
            payChannelService.saveRequestLocal(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.MERCHANT_ACCESS);
        }
        CommonResult<MerchantProductQueryResp> commonResult = null;
        if (merchantBusinessContext.isProcessStatus()) {
            commonResult = CommonResult.success(resp);
        }
        else {
            commonResult = CommonResult.error(1, merchantBusinessContext.getRemark());
        }
        return commonResult;
    }

    @Override
    public CommonResult<Integer> queryMerAuthStatus(MerchantAccessDto merchantAccessDto,MerchantAuthStatusConfig merchantAuthStatusConfig) {
        MerchantAccessInfoDO merchantAccessInfoDO = merchantAccessDto.getMerchantAccessInfo();
        ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(merchantAccessInfoDO.getProviderCode(), merchantAccessInfoDO.getChannelCode());
        ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext = new ChannelMerchantAccessAuthQueryContext();
        channelMerchantAccessAuthQueryContext.setMerchantAccessDto(merchantAccessDto);
        channelMerchantAccessAuthQueryContext.setMerchantAccessInfo(merchantAccessDto.getMerchantAccessInfo());
        channelMerchantAccessAuthQueryContext.setProviderChannelConfig(providerChannelConfigDO);
        channelMerchantAccessAuthQueryContext.setMerchantAuthStatusConfig(merchantAuthStatusConfig);
        channelMerchantAccessAuthQueryContext.setTest(test);
        Integer authStatus = extensionExecutor.execute(ChannelMerchantAccessExtPt.class, BizScenario.valueOf(merchantAccessInfoDO.getChannelCode()),
                ex -> ex.queryMerAuthStatus(channelMerchantAccessAuthQueryContext));
        return CommonResult.success(authStatus);
    }

    List<PayCommonAppDto> payCommonAppList(Set<Long> appIds, MerchantAccessDto merchantAccessDto) {
        if (CollectionUtils.isEmpty(appIds)) {
            return Collections.emptyList();
        }
        appIds.remove(null);
        if (CollectionUtils.isEmpty(appIds)) {
            return Collections.emptyList();
        }
        List<PayCommonAppDto> payCommonAppDtos = new ArrayList<>();
        List<CommonAppDO> commonAppList = commonAppConfigService.queryListByIds(List.copyOf(appIds));
        Integer sceneType = merchantAccessDto.getMerchantAccessBusiness().getSceneType();
        PayWayQueryDto payWayQueryDto = new PayWayQueryDto();
        payWayQueryDto.setTypes(new ArrayList<>() {

            {
                add(PayEnums.PAY_TYPE.WECHAT.getCode());
                add(PayEnums.PAY_TYPE.ALIPAY.getCode());
            }
        });
        payWayQueryDto.setSceneType(sceneType);
        List<PayWayDO> payWayList = payWayService.queryList(payWayQueryDto);
        Map<String, PayWayDO> payWayMap = payWayList.stream()
                .collect(Collectors.toMap(payWayDO -> key(payWayDO.getType(), payWayDO.getSubType()), Function.identity(), (t1, t2) -> t1));
        commonAppList.stream().forEach(commonAppDO -> {
            PayCommonAppDto payCommonAppDto = BeanUtil.copyProperties(commonAppDO, PayCommonAppDto.class);
            CommonEnum.COMMON_APP_TYPE commonAppType = CommonEnum.COMMON_APP_TYPE.from(payCommonAppDto.getType());
            String key = "";
            switch (commonAppType) {
                case WECHAT_PUB:
                    key = key(PayEnums.PAY_TYPE.WECHAT.getCode(), PayEnums.SCENE_PAY_TYPE.JSAPI.getType());
                    break;
                case WECHAT_MIN:
                    key = key(PayEnums.PAY_TYPE.WECHAT.getCode(), PayEnums.SCENE_PAY_TYPE.MINI_APP.getType());
                    break;
                case ALIPAY_PUB:
                    key = key(PayEnums.PAY_TYPE.ALIPAY.getCode(), PayEnums.SCENE_PAY_TYPE.JSAPI.getType());
                    break;
                case ALIPAY_MIN:
                    key = key(PayEnums.PAY_TYPE.ALIPAY.getCode(), PayEnums.SCENE_PAY_TYPE.MINI_APP.getType());
                    break;
            }
            payCommonAppDto.setPayWayDO(payWayMap.get(key));
            payCommonAppDtos.add(payCommonAppDto);
        });
        return payCommonAppDtos;
    }

    public String key(Integer type, String subType) {
        return type + "_" + subType;
    }
}
